﻿namespace IceCS.DataStructure.Core.Queue
{
    /// <summary>
    /// 
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class CircleSequenceQueue<T> : IQueue<T>
    {
        private T[] _data;

        /// <summary>
        /// 队列的最大容量
        /// </summary>
        public int MaxCount { get; set; }

        /// <summary>
        /// 队列头指示器
        /// </summary>
        public int Front { get; set; }

        /// <summary>
        /// 队列尾指示器
        /// </summary>
        public int Rear { get; set; }

        /// <summary>
        /// 元素数量
        /// </summary>
        public int Count { get; private set; }

        /// <summary>
        /// 索引器
        /// </summary>
        /// <param name="index"></param>
        /// <returns></returns>
        public T this[int index]
        {
            get { return _data[index]; }
            set { _data[index] = value; }
        }

        /// <summary>
        /// 
        /// </summary>
        public CircleSequenceQueue()
        {

        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="size"></param>
        public CircleSequenceQueue(int size)
        {
            _data = new T[size];
            MaxCount = size;
            Front = Rear = -1;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public int GetLength()
        {
            return (Rear - Front + MaxCount) % MaxCount;
        }

        /// <summary>
        /// 
        /// </summary>
        public void Clear()
        {
            Front = Rear = -1;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="data"></param>
        public void Enqueue(T data)
        {
            if (IsFull)
            {
                return;
            }
            Rear = (Rear + 1) % MaxCount;
            _data[Rear] = data;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public T Dequeue()
        {
            if (IsFull)
            {
                return default(T);
            }
            Front = (Front + 1) % MaxCount;
            return _data[Front];
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public T Peek()
        {
            if (IsFull)
            {
                return default(T);
            }
            return _data[(Front + 1) % MaxCount];
        }

        /// <summary>
        /// 
        /// </summary>
        public bool IsFull => (Front == -1 && Rear == MaxCount - 1) || (Rear + 1) % MaxCount == Front;

        /// <summary>
        /// 
        /// </summary>
        public bool IsEmpty => Front == Rear;
    }
}
